global FTOOLS_TYPE_TEXT = 0	-- text value
global FTOOLS_TYPE_FIXED16 = 1	-- 16 bit fixed point

global ftools_export_type = FTOOLS_TYPE_FIXED16
global ftools_export_scale = 1

global ftools_exportObject


-- creates the specified file, returns the stream
fn ftools_createFile fname =
(
	if (ftools_export_type == FTOOLS_TYPE_TEXT) do
	(
		strm = createFile fname
		return strm
	)
	
	if (ftools_export_type == FTOOLS_TYPE_FIXED16) do
	(
		strm = fopen fname "wb"
		return strm
	)
)

-- closes the specified stream
fn ftools_closeFile strm =
(
	if (ftools_export_type == FTOOLS_TYPE_TEXT) do
	(
		close strm
	)
	
	if (ftools_export_type == FTOOLS_TYPE_FIXED16) do
	(
		FClose strm
	)
)

-- writes the float value to the stream, according to it's type
fn ftools_writeFloat val strm =
(
	if (ftools_export_type == FTOOLS_TYPE_TEXT) do	--textFile
	(
		v = (((val * 100000) as Integer) as Float) / 100000
		format "% " v to:strm
	)
	
	if (ftools_export_type == FTOOLS_TYPE_FIXED16) do	--binaryFile
	(
		v = ((val * ftools_export_scale) * 4096) as Integer;
		writeShort strm v
	)	
)

-- writes the int value to the stream, according to it's type
fn ftools_writeByte val strm =
(
	if (ftools_export_type == FTOOLS_TYPE_TEXT) do	--textFile
	(
		v = val as Integer
		format "% " v to:strm
	)
	
	if (ftools_export_type == FTOOLS_TYPE_FIXED16) do	--binaryFile
	(
		v = val as Integer;
		writeByte strm v
	)	
)

-- writes the int value to the stream, according to it's type
fn ftools_writeShort val strm =
(
	if (ftools_export_type == FTOOLS_TYPE_TEXT) do	--textFile
	(
		v = val as Integer
		format "% " v to:strm
	)
	
	if (ftools_export_type == FTOOLS_TYPE_FIXED16) do	--binaryFile
	(
		v = val as Integer;
		writeShort strm v
	)	
)

-- writes the int value to the stream, according to it's type
fn ftools_writeLong val strm =
(
	if (ftools_export_type == FTOOLS_TYPE_TEXT) do	--textFile
	(
		v = val as Integer
		format "% " v to:strm
	)
	
	if (ftools_export_type == FTOOLS_TYPE_FIXED16) do	--binaryFile
	(
		v = val as Integer;
		writeLong strm v
	)	
)

-- writes a new line (only for text files)
fn ftools_newLine strm =
(
	if (ftools_export_type == FTOOLS_TYPE_TEXT) do
		format "\n" to:strm
)

-- writes the comment (only for text files)
fn ftools_comment text strm =
(
	if (ftools_export_type == FTOOLS_TYPE_TEXT) do
	(
		format "#%\n" text to:strm
	)
)

-- writes the string (only for text files)
fn ftools_writeString text strm =
(
	if (ftools_export_type == FTOOLS_TYPE_TEXT) do
	(
		format "%" text to:strm
	)
)

fn ftools_writeObjectHeader obj expSkin strm =
(
	-- must select the object for skinOps
	select obj

	-- get mesh and skin
	tmesh = snapshotAsMesh obj
	skinMod = obj.modifiers[#skin]
	
	if (skinMod == undefined) do
		expSkin = false
		
	-- write signature
	if (expSkin) then
	(
		if (ftools_export_type == FTOOLS_TYPE_TEXT) do
		(
			ftools_writeString "OBJa\n" strm
		)

		if (ftools_export_type == FTOOLS_TYPE_FIXED16) do
		(
			ftools_writeLong 0x614A424F strm	-- signature, OBJa
		)
	)
	else
	(
		if (ftools_export_type == FTOOLS_TYPE_TEXT) do
		(
			ftools_writeString "OBJs\n" strm
		)

		if (ftools_export_type == FTOOLS_TYPE_FIXED16) do
		(
			ftools_writeLong 0x734A424F strm	-- signature, OBJs
		)
	)
	
	-- write static counts
	num_verts = tmesh.numverts
	num_faces = tmesh.numfaces
	num_tverts = tmesh.numtverts
	
	ftools_comment "vertex count, face count, tex-vertex count" strm
	ftools_writeShort num_verts strm
	ftools_writeShort num_faces strm
	ftools_writeShort num_tverts strm
	ftools_newLine strm
	
	if (expSkin) do
	(
		-- write skin counts
		num_bones = (SkinOps.GetNumberBones skinMod)

		ftools_comment "bones count" strm
		ftools_writeShort num_bones strm		
		ftools_newLine strm
	)
		
	ftools_newLine strm
)

fn ftools_exportObjectMesh obj strm =
(
	-- get mesh
	tmesh = snapshotAsMesh obj

	-- get counts
	num_verts = tmesh.numverts
	num_faces = tmesh.numfaces
	num_tverts = tmesh.numtverts
		
	-- write vertex position
	ftools_export_scale = 1.0/40.0
	ftools_comment "Vertices (x, y, z)" strm
	for i = 1 to num_verts do
	(
		v = getVert tmesh i
		ftools_writeFloat v.x strm
		ftools_writeFloat v.y strm
		ftools_writeFloat v.z strm
		ftools_newLine strm
	)
	ftools_newLine strm
	ftools_export_scale = 1.0
	
	-- write face indices (0-based)
	ftools_comment "Faces (v1, v2, v3)" strm
	for i = 1 to num_faces do
	(
		f = getFace tmesh i
		ftools_writeShort (f.x - 1) strm
		ftools_writeShort (f.y - 1) strm
		ftools_writeShort (f.z - 1) strm
		ftools_newLine strm
	)
	ftools_newLine strm

	-- write texture coordinates
	ftools_comment "Texture vertices (u, v)" strm
	for i = 1 to num_tverts do
	(
		v = getTVert tmesh i
		ftools_writeFloat v.x strm
		ftools_writeFloat v.y strm
		ftools_newLine strm
	)
	ftools_newLine strm

	-- write texture face indices (0-based)
	ftools_comment "Texture faces (t1, t2, t3)" strm
	for i = 1 to num_faces do
	(
		f = getTVFace tmesh i
		ftools_writeShort (f.x - 1) strm
		ftools_writeShort (f.y - 1) strm
		ftools_writeShort (f.z - 1) strm
		ftools_newLine strm
	)
	ftools_newLine strm
	
	-- write face normals (n1x, n1y, n1z, n2x, n2y, n2z, n3x, n3y, n3z)
	ftools_comment "Normal faces" strm	
	for i = 1 to num_faces do
	(
		normals = meshop.getFaceRNormals tmesh i
		
		ftools_writeFloat normals[1].x strm
		ftools_writeFloat normals[1].y strm
		ftools_writeFloat normals[1].z strm
		ftools_writeString "   " strm
		
		ftools_writeFloat normals[2].x strm
		ftools_writeFloat normals[2].y strm
		ftools_writeFloat normals[2].z strm
		ftools_writeString "   " strm

		ftools_writeFloat normals[3].x strm
		ftools_writeFloat normals[3].y strm
		ftools_writeFloat normals[3].z strm
		ftools_newLine strm
	)

	ftools_newLine strm
)

fn ftools_exportSkinInfo obj strm =
(
	-- must select the object for skinOps
	select obj
	
	-- get the skin
	skinMod = obj.modifiers[#skin]
	if (skinMod == undefined) do
		return 0
	
	num_verts = skinOps.GetNumberVertices skinMod

	-- write vertex weights
	
	ftools_comment "Vertex weights (bone count, boneID1, weight1, boneID2, weight2,...)" strm
	for i = 1 to num_verts do
	(
		n = skinOps.GetVertexWeightCount skinMod i
		ftools_writeByte n strm
		
		for j = 1 to n do
		(
			boneID = (SkinOps.GetVertexWeightBoneID skinMod i j) - 1
			weight = (SkinOps.GetVertexWeight skinMod i j)
			
			ftools_writeByte boneID strm
			
			-- if text file, write weight as float
			if (ftools_export_type == FTOOLS_TYPE_TEXT) do
			(
				ftools_writeFloat weight strm
			)
			
			-- if binary, write weight as a value between 0(no influence) and 255(full influence)
			if (ftools_export_type == FTOOLS_TYPE_FIXED16) do
			(
				ftools_writeByte (weight * 255) strm
			)
		)
		ftools_newLine strm
	)
	
	ftools_newLine strm
	
	ftools_comment "Bone hierarchy (parentID, name)" strm
	num_bones = (SkinOps.GetNumberBones skinMod)
	bones = #()
	for i = 1 to num_bones do
		append bones (SkinOps.getBoneName skinMod i 0)
			
	for i = 1 to num_bones do	
	(
		bname = bones[i]
		bone = execute("$" + bname)
		pid = 0
		if (bone.parent != undefined) do
		(
			pname = bone.parent.name
			pid = findItem bones pname
		)
		ftools_writeByte (pid-1) strm
		ftools_writeString bname strm
		ftools_newLine strm
	)
	
	ftools_newLine strm	
)


fn ftools_exportObject obj expSkin fname =
(
	strm = ftools_createFile fname
	
	ftools_writeObjectHeader obj expSkin strm
	ftools_exportObjectMesh obj strm
	
	if (expSkin) do
	(
		ftools_exportSkinInfo obj strm
	)
			
	ftools_closeFile strm
)